package com.share.order.receiver;

import com.alibaba.fastjson2.JSONObject;
import com.rabbitmq.client.Channel;
import com.share.common.core.utils.StringUtils;
import com.share.common.rabbit.constant.MqConst;
import com.share.order.api.domain.EndOrderVo;
import com.share.order.api.domain.SubmitOrderVo;
import com.share.order.service.IOrderInfoService;
import lombok.SneakyThrows;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author YC
 */
@Component
public class OrderReceiver {

    @Autowired
    private IOrderInfoService orderInfoService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 充电宝弹出，接收消息生成订单
     *
     * @param content 消息队列接受的内容
     * @param message 消息
     * @param channel 通道
     */
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_ORDER, durable = "true"),
            value = @Queue(value = MqConst.QUEUE_SUBMIT_ORDER, durable = "true"),
            key = MqConst.ROUTING_SUBMIT_ORDER
    ))
    public void createOrder(String content, Message message, Channel channel) {
        // 把content转换对象
        SubmitOrderVo submitOrderVo = JSONObject.parseObject(content, SubmitOrderVo.class);
        // 防止重复消费
        String messageNo = submitOrderVo.getMessageNo();
        String key = "order:endorder:" + messageNo;
        Boolean ifAbsent = redisTemplate.opsForValue().setIfAbsent(key, messageNo, 1, TimeUnit.HOURS);
        if (Boolean.FALSE.equals(ifAbsent)) {
            return;
        }
        // 调用生成订单接口
        try {
            Long orderId = orderInfoService.saveOrder(submitOrderVo);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 充电宝插入，接收消息结束订单
     *
     * @param content 消息队列接受的内容
     * @param message 消息
     * @param channel 通道
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_ORDER, durable = "true"),
            value = @Queue(value = MqConst.QUEUE_END_ORDER, durable = "true"),
            key = MqConst.ROUTING_END_ORDER
    ))
    public void endOrder(String content, Message message, Channel channel) {
        // 把content转换对象
        EndOrderVo endOrderVo = JSONObject.parseObject(content, EndOrderVo.class);
        // 防止重复消费
        String messageNo = endOrderVo.getMessageNo();
        String key = "order:endorder:" + messageNo;
        Boolean ifAbsent = redisTemplate.opsForValue().setIfAbsent(key, messageNo, 1, TimeUnit.HOURS);
        if (Boolean.FALSE.equals(ifAbsent)) {
            return;
        }
        // 调用结束订单接口
        try {
            orderInfoService.endOrder(endOrderVo);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            redisTemplate.delete(key);
            //消息重新回到队列
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }

    /**
     * 微信支付成功，接收RabbitMQ消息队列消息 修改订单状态
     *
     * @param orderNo 订单号
     * @param message 消息
     * @param channel 通道
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_PAYMENT_PAY, durable = "true"),
            value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY, durable = "true"),
            key = MqConst.ROUTING_PAYMENT_PAY
    ))
    public void processPaySuccess(String orderNo, Message message, Channel channel) {
        if (StringUtils.isNotEmpty(orderNo)) {
            // 更改订单支付状态
            orderInfoService.processPaySuccess(orderNo);
        }
        // 手动应答
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}
